package com.alibaba.citrus.cr.mn.order.center.facade.service.impl;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.enums.ordercenter.*;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.lock.SaleRedisLock;
import com.alibaba.citrus.cr.mn.order.center.common.SetOrderTag;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.TrimUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.function.asynctask.AsyncTaskCreateService;
import com.alibaba.citrus.cr.mn.order.center.facade.function.check.AbstractOrderParamsCheckService;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.*;
import com.alibaba.citrus.cr.mn.order.center.facade.function.convert.ObtcSaleOrderLineIndexToResponseConvertor;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crb2btradecenter.model.enums.MessageTaskTypeEnum;
import com.epoch.app.crb2btradecenter.obtcsaleorderlineindex.model.ObtcSaleOrderLineIndex;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.orderbaserequest.*;
import com.epoch.app.mnordercenter.salesorderbiz.service.SalesOrderBizService;
import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.alibaba.citrus.cr.mn.order.center.common.constants.RedisLockConstants.*;

/**
 * @author zhangxiaorui
 * @date 2023/05/16 11:11
 */
@Primary
@Component
public class SalesOrderBizServiceImpl implements SalesOrderBizService {

    private static final Log log = Log.getLogger(SalesOrderBizServiceImpl.class);

    @Resource
    private AsyncTaskCreateService asyncTaskCreateService;
    @Resource(name = "salesOrderBizCloseService")
    private OrderBizCloseService salesOrderBizCloseService;
    @Resource(name = "salesOrderBizSubmitService")
    private OrderBizSubmitService salesOrderBizSubmitService;
    @Resource
    private SendMsgService sendMsgService;
    @Resource(name = "salesOrderBizCreateParamsCheck")
    private AbstractOrderParamsCheckService salesOrderBizCreateParamsCheck;
    @Resource(name = "salesOrderBizUpdateService")
    private OrderBizUpdateService<OrderBizUpdateRequest, OrderAtomUpdateRequest, OrderAtomUpdateResponse> salesOrderBizUpdateService;
    @Resource(name = "salesOrderAtomQueryService")
    private OrderAtomQueryService salesOrderAtomQueryService;
    @Resource(name = "salesOrderBizCreateService")
    private OrderBizCreateService<SalesOrderBizBatchCreateRequest, SalesOrderAtomBatchCreateRequest, OrderAtomCreateResponse> salesOrderBizCreateService;

    @Override
    @FacadeInvoker(value = "销售订单批量创建", errorCode = "OC-01-001-01-16-006")
    public Result<SalesOrderBizCreateResponse> batchCreate(SalesOrderBizBatchCreateRequest request) {
        log.info("SalesOrderBizServiceImpl#batchCreate request={}", JSON.toJSONString(request));
        AssertUtils.isTrue(StringUtils.isBlank(request.getReqNo()), "OC-01-001-01-15-001", "请求编码");

        if ("APP_MDG".equals(request.getFromSys())) {
            log.info("SalesOrderBizServiceImpl#batchCreate filter request");
            // 测试100主各10子报文传输时间
            SalesOrderBizCreateResponse salesOrderBizCreateResponse = new SalesOrderBizCreateResponse();
            salesOrderBizCreateResponse.setBatchTaskId(String.valueOf(System.currentTimeMillis()));
            return Result.success(salesOrderBizCreateResponse, "", "");
        }

        String lockKey = SALES_ORDER_BIZ_PREFIX + request.getReqNo();
        log.info("SalesOrderBizServiceImpl#batchCreate lockKey={}", lockKey);
        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderBizServiceImpl#batchCreate 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("订单中心一盘货销售订单", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心一盘货销售订单", "paramsInvalidCheck");
            AssertUtils.lengthCheck(request.getReqNo(), 128, true, "OC-01-001-01-15-004", "请求编码");
            AssertUtils.isTrue(CollectionUtils.isEmpty(request.getOrderList()), "OC-01-001-01-15-001", "单据列表");
            request.getOrderList().parallelStream().forEach(order -> {
                if (StringUtils.isNotBlank(request.getFromSys())) {
                    order.setFromSys(request.getFromSys());
                }
                if (StringUtils.isNotBlank(request.getBusinessType())) {
                    order.setBusinessType(request.getBusinessType());
                }
                if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                    order.setBusinessUnitCode(request.getBusinessUnitCode());
                }

                if (StringUtils.isBlank(order.getFulfillmentTypeCode())) {
                    order.setFulfillmentTypeCode(FulfillmentTypeEnum.EXTERNAL_TO_DELIVERY.getCode());
                }
                if (StringUtils.isBlank(order.getFulfillmentPriority())) {
                    order.setFulfillmentPriority(FulfillmentPriorityEnum.NORMAL.getCode());
                }
                if (StringUtils.isBlank(order.getAutoFulfillment())) {
                    order.setAutoFulfillment(Boolean.TRUE.toString());
                }
                if (StringUtils.isBlank(order.getOrderChannelCode())) {
                    order.setOrderChannelCode(OrderChannelEnum.COMPANY.getCode());
                }
                if (Objects.isNull(order.getCheckCredit())) {
                    order.setCheckCredit(Boolean.TRUE);
                }
                if (Objects.isNull(order.getCheckStock())) {
                    order.setCheckStock(Boolean.TRUE);
                }
                if (Objects.isNull(order.getIsSubmit())) {
                    order.setIsSubmit(Boolean.TRUE);
                }
                order.setCheckCreditB(Boolean.FALSE);
                order.setOrderCategoryCode(OrderCategoryEnum.COMPANY.getCode());

            });
            salesOrderBizCreateParamsCheck.paramsInvalidCheck(request.getOrderList(), new ArrayList<>());
            StopWatchUtils.stop();

            String batchTaskId = asyncTaskCreateService.createAsyncTask(request.getFromSys() + "#" + request.getReqNo(),
                    request.getFromSys(), JSON.toJSONString(request), MessageTaskTypeEnum.OC_SALES_ORDER_BATCH_CREATE);

            StopWatchUtils.start("订单中心一盘货销售订单", "salesOrderBizCreateResponse");
            SalesOrderBizCreateResponse salesOrderBizCreateResponse = new SalesOrderBizCreateResponse();
            salesOrderBizCreateResponse.setBatchTaskId(batchTaskId);
            StopWatchUtils.stop();
            return Result.success(salesOrderBizCreateResponse, "", "");

        } catch (Exception e) {
            StopWatchUtils.stop();
            log.error("SalesOrderBizServiceImpl#batchCreate error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderBizServiceImpl#batchCreate");
        }
    }

    @Override
    @FacadeInvoker(value = "销售订单批量提交", errorCode = "OC-01-003-01-16-002")
    public Result<List<OrderAtomSubmitResponse>> batchSubmit(OrderBizBatchSubmitRequest request) {
        log.info("SalesOrderBizServiceImpl#batchSubmit request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_BIZ_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderBizServiceImpl#batchSubmit lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderBizServiceImpl#batchSubmit 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            for (OrderAtomSubmitRequest salesOrder : request.getOrderList()) {
                if (Objects.isNull(salesOrder.getCheckStock())) {
                    salesOrder.setCheckStock(Boolean.TRUE);
                }
                if (Objects.isNull(salesOrder.getCheckCredit())) {
                    salesOrder.setCheckCredit(Boolean.TRUE);
                }
                salesOrder.setCheckCreditB(Boolean.FALSE);
            }
            request.setOrderCategoryCode(OrderCategoryEnum.COMPANY.getCode());

            List<OrderAtomSubmitResponse> resp = salesOrderBizSubmitService.batchSubmit(request);
            if (CollectionUtils.isNotEmpty(resp)) {
                // 发送消息通知来源系统
                List<PushOrderInfoToMnSideRequestOrderInfo> pushOrderInfoList = new ArrayList<>();
                for (OrderAtomSubmitResponse submitResponse : resp) {
                    pushOrderInfoList.add(PushOrderInfoToMnSideRequestOrderInfo.builder()
                            .salesOrderNo(submitResponse.getSalesOrderNo())
                            .orderStatus(SalesOrderPushStatusEnum.FAIL_UPDATE.getOrderStatusCode())
                            .message(submitResponse.getMessage())
                            .build());
                }
                // 发送kafka消息通知应用端处理结果
//                sendMsgService.sendMsgToNYK(pushOrderInfoList);
                CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
                commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getValue());
                commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getLabel());
                commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
                commonAsyncMessageResponse.setFromSys(request.getFromSys());
                commonAsyncMessageResponse.setBusinessUnitCode(request.getBusinessUnitCode());
                commonAsyncMessageResponse.setData(pushOrderInfoList);
                sendMsgService.sendMsgToSendKafka(commonAsyncMessageResponse);
                log.info("SalesOrderBizServiceImpl#batchSubmit sendMsgToSendKafka message={}", commonAsyncMessageResponse);
            }
            return Result.success(resp, "", "");
        } catch (Exception e) {
            log.error("SalesOrderBizServiceImpl#batchSubmit error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderBizServiceImpl#batchSubmit");
        }
    }

    @FacadeInvoker(value = "销售订单批量关闭", errorCode = "OC-01-003-01-16-003")
    @Override
    public Result<List<OrderAtomCloseResponse>> batchClose(OrderBizBatchCloseRequest request) {
        log.info("SalesOrderBizServiceImpl#batchClose request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_BIZ_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderBizServiceImpl#batchClose lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderBizServiceImpl#batchClose 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            return salesOrderBizCloseService.batchClose(request);
        } catch (Exception e) {
            log.error("SalesOrderBizServiceImpl#batchClose error", e);
            throw e;
        }
    }

    @FacadeInvoker(value = "销售订单修改", errorCode = "OC-01-001-01-16-013")
    @Override
    public Result<OrderBizUpdateResponse> update(OrderBizUpdateRequest request) {
        log.info("SalesOrderBizServiceImpl#update request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_BIZ_PREFIX + request.getSalesOrderNo();
        log.info("SalesOrderBizServiceImpl#update lockKey={}", lockKey);
        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderBizServiceImpl#update 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            request.setOrderCategoryCode(OrderCategoryEnum.COMPANY.getCode());
            if (Objects.isNull(request.getCheckCredit())) {
                request.setCheckCredit(Boolean.TRUE);
            }
            if (Objects.isNull(request.getCheckStock())) {
                request.setCheckStock(Boolean.TRUE);
            }
            request.setCheckCreditB(Boolean.FALSE);
            OrderAtomUpdateResponse atomUpdateResponse = salesOrderBizUpdateService.update(request);
            OrderBizUpdateResponse bizUpdateResponse = new OrderBizUpdateResponse();
            BeanUtils.copyProperties(atomUpdateResponse, bizUpdateResponse);
            if (StringUtils.isNotBlank(bizUpdateResponse.getErrorCode())) {
                if (CollectionUtils.isNotEmpty(atomUpdateResponse.getOrderDetails())) {
                    return Result.fail(bizUpdateResponse, "", "");
                }
                return Result.fail(bizUpdateResponse.getErrorCode(), atomUpdateResponse.getMessage());
            }
            return Result.success(bizUpdateResponse, "", "");
        } catch (Exception e) {
            log.error("SalesOrderBizServiceImpl#update error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderBizServiceImpl#update");
        }
    }


    @Override
    @FacadeInvoker(value = "B2b销售明细列表分页查询", errorCode = "OC-01-003-01-16-008")
    public Result<List<PageQuerySaleOrderDetailResponse>> loadDetailForPage(SalesOrderGroupPageQueryRequest request) {
        // 校验销售订单的单据类型
        List<String> salesOrderType = request.getSalesOrderTypeList();
        if (org.apache.commons.collections.CollectionUtils.isEmpty(salesOrderType)) {
            request.setSalesOrderTypeList(SalesOrderTypeEnum.companyOrderCodes());
        } else {
            AssertUtils.isTrue(salesOrderType.size() > 10, "OC-01-001-01-15-004", "订单类型编码集合", request.getSalesOrderTypeList().size(), "10");
            salesOrderType.forEach(tmpSalesOrderCode -> {
                AssertUtils.lengthCheck(tmpSalesOrderCode, 50, false, "OC-01-001-01-15-004", "订单类型编码");
                if (Objects.isNull(SalesOrderTypeEnum.of(tmpSalesOrderCode))) {
                    throw new FunctionException("OC-01-001-01-15-006", "订单类型编码");
                }
            });
        }
        if (org.apache.commons.lang.StringUtils.isBlank(request.getOrderCategoryCode())) {
            request.setOrderCategoryCodeList(Lists.newArrayList(OrderCategoryEnum.COMPANY.getCode(), OrderCategoryEnum.STOCK.getCode()));
        } else {
            AssertUtils.lengthCheck(request.getOrderCategoryCode(), 50, false, "OC-01-001-01-15-004", "订单类别编码");
            AssertUtils.isTrue(!OrderCategoryEnum.codes().contains(request.getOrderCategoryCode()), "OC-01-001-01-15-006", "订单类别编码");
        }
        if (StringUtils.isBlank(request.getOrderTag())) {
            request.setOrderTag(SetOrderTag.NORMAL);
        }
        SalesOrderAtomPageQueryRequest salesOrderAtomPageQueryRequest = new SalesOrderAtomPageQueryRequest();
        BeanUtils.copyProperties(request, salesOrderAtomPageQueryRequest);
        Result<List<ObtcSaleOrderLineIndex>> listResult = salesOrderAtomQueryService.detailListPage(salesOrderAtomPageQueryRequest);
        List<PageQuerySaleOrderDetailResponse> response = ObtcSaleOrderLineIndexToResponseConvertor.convert(listResult, null);
        Result<List<PageQuerySaleOrderDetailResponse>> success = Result.success(response, "", "");
        success.setTotal(listResult.getTotal());
        return success;
    }

    @Override
    @FacadeInvoker(value = "销售订单商业同步创建", errorCode = "OC-01-001-01-16-006")
    public Result<OrderAtomCreateResponse> create(SalesOrderBizCreateRequest request) {
        AssertUtils.isTrue(StringUtils.isBlank(request.getReqNo()), "OC-01-001-01-15-001", "请求编码");
        log.info("SalesOrderBizServiceImpl#create request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_BIZ_PREFIX + request.getReqNo();
        log.info("SalesOrderBizServiceImpl#create lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderBizServiceImpl#create 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            StopWatchUtils.start("订单中心商业同步创建", "removeSpace");
            TrimUtils.removeSpace(request);
            StopWatchUtils.stop();

            StopWatchUtils.start("订单中心商业同步创建", "paramsInvalidCheck");
            AssertUtils.lengthCheck(request.getReqNo(), 128, true, "OC-01-001-01-15-004", "请求编码");
            AssertUtils.isTrue(Objects.isNull(request), "OC-01-001-01-15-001", "单据列表");

            // 设置默认履约方式
            if (StringUtils.isBlank(request.getFulfillmentTypeCode())) {
                request.setFulfillmentTypeCode(FulfillmentTypeEnum.CENTRAL_DELIVERY.getCode());
            }
            if (StringUtils.isBlank(request.getOrderCategoryCode())) {
                request.setOrderCategoryCode(OrderCategoryEnum.COMPANY.getCode());
            }
            if (StringUtils.isBlank(request.getOrderChannelCode())) {
                request.setOrderChannelCode(OrderChannelEnum.COMPANY.getCode());
            }
            if (StringUtils.isNotBlank(request.getFromSys())) {
                request.setFromSys(request.getFromSys());
            }
            if (StringUtils.isNotBlank(request.getBusinessType())) {
                request.setBusinessType(request.getBusinessType());
            }
            if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                request.setBusinessUnitCode(request.getBusinessUnitCode());
            }
            if (StringUtils.isBlank(request.getFulfillmentPriority())) {
                // 默认普通
                request.setFulfillmentPriority(FulfillmentPriorityEnum.NORMAL.getCode());
            }
            if (StringUtils.isBlank(request.getAutoFulfillment())) {
                // 默认自动创建履约单
                request.setAutoFulfillment(Boolean.TRUE.toString());
            }
            if (Objects.isNull(request.getCheckCredit())) {
                request.setCheckCredit(Boolean.TRUE);
            }
            if (Objects.isNull(request.getCheckStock())) {
                request.setCheckStock(Boolean.TRUE);
            }
            if (Objects.isNull(request.getIsSubmit())) {
                request.setIsSubmit(Boolean.TRUE);
            }
            request.setCheckCreditB(Boolean.FALSE);
            List<SalesOrderBizCreateRequest> salesOrderBizCreateRequestList = Lists.newArrayList(request);
            salesOrderBizCreateParamsCheck.paramsInvalidCheck(salesOrderBizCreateRequestList, new ArrayList<>());
            StopWatchUtils.stop();
            StopWatchUtils.start("订单中心商业同步创建", "create");

            // 组装同步创建入参
            SalesOrderBizBatchCreateRequest createRequest = new SalesOrderBizBatchCreateRequest();
            createRequest.setReqNo(request.getReqNo());
            createRequest.setBusinessType(request.getBusinessType());
            createRequest.setBusinessUnitCode(request.getBusinessUnitCode());
            createRequest.setFromSys(request.getFromSys());
            createRequest.setOrderList(salesOrderBizCreateRequestList);
            List<OrderAtomCreateResponse> createResponses = salesOrderBizCreateService.batchCreate(createRequest);
            OrderAtomCreateResponse orderAtomCreateResponse = createResponses.get(0);
            if (StringUtils.isNotBlank(orderAtomCreateResponse.getErrorCode())) {
                return Result.fail(orderAtomCreateResponse, orderAtomCreateResponse.getErrorCode(), orderAtomCreateResponse.getMessage());
            } else {
                return Result.success(orderAtomCreateResponse, "", "");
            }
        } catch (Exception e) {
            StopWatchUtils.stop();
            log.error("SalesOrderBizServiceImpl#create error", e);
            throw e;
        } finally {
            StopWatchUtils.print("SalesOrderBizServiceImpl#create");
        }
    }
}
